#ifndef __EASY_HOOK_H__
#define __EASY_HOOK_H__

#include <Windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <functional>
#include "MinHook.h"

namespace EasyHook
{

// Hook管理器类 - 单例模式
class HookManager
{
public:
    static HookManager &getInstance()
    {
        static HookManager instance;
        return instance;
    }

    // 初始化Hook系统
    inline bool initialize()
    {
        if (initialized_)
        {
            return true;
        }

        MH_STATUS status = MH_Initialize();
        if (status != MH_OK)
        {
            setError("Failed to initialize MinHook: " + statusToString(status));
            return false;
        }

        initialized_ = true;
        return true;
    }

    // 清理Hook系统
    inline bool cleanup()
    {
        if (!initialized_)
        {
            return true;
        }

        // 禁用所有Hook
        disableAllHooks();

        // 清理MinHook
        MH_STATUS status = MH_Uninitialize();
        if (status != MH_OK)
        {
            setError("Failed to uninitialize MinHook: " + statusToString(status));
            return false;
        }

        initialized_ = false;
        hooks_.clear();
        return true;
    }

    // 创建并启用Hook
    template<typename FuncType>
    inline bool createHook(FuncType targetFunc, FuncType detourFunc, FuncType *originalFunc = nullptr)
    {
        if (!initialized_ && !initialize())
        {
            return false;
        }

        MH_STATUS status = MH_CreateHook(reinterpret_cast<LPVOID>(targetFunc), reinterpret_cast<LPVOID>(detourFunc), reinterpret_cast<LPVOID *>(originalFunc));

        if (status != MH_OK)
        {
            setError("Failed to create hook: " + statusToString(status));
            return false;
        }

        status = MH_EnableHook(reinterpret_cast<LPVOID>(targetFunc));
        if (status != MH_OK)
        {
            setError("Failed to enable hook: " + statusToString(status));
            return false;
        }

        hooks_.push_back(reinterpret_cast<LPVOID>(targetFunc));
        return true;
    }

    // 通过函数名创建Hook（用于系统API）
    inline bool createAPIHook(const std::string &moduleName, const std::string &funcName, LPVOID detourFunc, LPVOID *originalFunc = nullptr)
    {
        if (!initialized_ && !initialize())
        {
            return false;
        }

        // 转换字符串为宽字符
        std::wstring wModuleName(moduleName.begin(), moduleName.end());

        MH_STATUS status = MH_CreateHookApi(wModuleName.c_str(), funcName.c_str(), detourFunc, originalFunc);

        if (status != MH_OK)
        {
            setError("Failed to create API hook for " + moduleName + "::" + funcName + ": " + statusToString(status));
            return false;
        }

        HMODULE hModule = GetModuleHandleA(moduleName.c_str());
        if (hModule)
        {
            LPVOID targetFunc = GetProcAddress(hModule, funcName.c_str());
            if (targetFunc)
            {
                status = MH_EnableHook(targetFunc);
                if (status != MH_OK)
                {
                    setError("Failed to enable API hook: " + statusToString(status));
                    return false;
                }
                hooks_.push_back(targetFunc);
            }
        }

        return true;
    }

    // ================================
    // 新增：扩展功能
    // ================================

    // 通过偏移获取地址
    inline LPVOID GetAddressByOffset(const std::string &moduleName, DWORD offset)
    {
        HMODULE hModule = GetModuleHandleA(moduleName.c_str());
        if (!hModule)
        {
            setError("Failed to get module handle for: " + moduleName);
            return nullptr;
        }

        return reinterpret_cast<LPVOID>(reinterpret_cast<uintptr_t>(hModule) + offset);
    }

    // 通过函数名获取地址
    inline LPVOID GetFunctionAddress(const std::string &moduleName, const std::string &functionName)
    {
        HMODULE hModule = GetModuleHandleA(moduleName.c_str());
        if (!hModule)
        {
            setError("Failed to get module handle for: " + moduleName);
            return nullptr;
        }

        LPVOID funcAddr = GetProcAddress(hModule, functionName.c_str());
        if (!funcAddr)
        {
            setError("Failed to get function address for: " + moduleName + "::" + functionName);
            return nullptr;
        }

        return funcAddr;
    }

    // 通过偏移创建Hook
    inline bool createOffsetHook(const std::string &moduleName, DWORD offset, LPVOID detourFunc, LPVOID *originalFunc = nullptr)
    {
        if (!initialized_ && !initialize())
        {
            return false;
        }

        // 获取目标地址
        LPVOID targetAddr = GetAddressByOffset(moduleName, offset);
        if (!targetAddr)
        {
            return false;
        }

        // 创建Hook
        MH_STATUS status = MH_CreateHook(targetAddr, detourFunc, originalFunc);
        if (status != MH_OK)
        {
            setError("Failed to create offset hook for " + moduleName + "+0x" + std::to_string(offset) + ": " + statusToString(status));
            return false;
        }

        // 启用Hook
        status = MH_EnableHook(targetAddr);
        if (status != MH_OK)
        {
            setError("Failed to enable offset hook: " + statusToString(status));
            return false;
        }

        hooks_.push_back(targetAddr);
        return true;
    }

    // 启用所有Hook
    inline bool enableAllHooks()
    {
        MH_STATUS status = MH_EnableHook(MH_ALL_HOOKS);
        if (status != MH_OK)
        {
            setError("Failed to enable all hooks: " + statusToString(status));
            return false;
        }
        return true;
    }

    // 禁用所有Hook
    inline bool disableAllHooks()
    {
        MH_STATUS status = MH_DisableHook(MH_ALL_HOOKS);
        if (status != MH_OK)
        {
            setError("Failed to disable all hooks: " + statusToString(status));
            return false;
        }
        return true;
    }

    // 获取最后的错误信息
    std::string getLastError() const
    {
        return lastError_;
    }

private:
    HookManager() = default;
    ~HookManager()
    {
        cleanup();
    }

    // 禁止拷贝
    HookManager(const HookManager &)            = delete;
    HookManager &operator=(const HookManager &) = delete;

    bool                initialized_ = false;
    std::string         lastError_;
    std::vector<LPVOID> hooks_; // 保存所有创建的Hook的目标地址

    inline void setError(const std::string &error)
    {
        lastError_ = error;
    }

    inline std::string statusToString(MH_STATUS status)
    {
        switch (status)
        {
        case MH_OK:
            return "MH_OK";
        case MH_ERROR_ALREADY_INITIALIZED:
            return "MH_ERROR_ALREADY_INITIALIZED";
        case MH_ERROR_NOT_INITIALIZED:
            return "MH_ERROR_NOT_INITIALIZED";
        case MH_ERROR_ALREADY_CREATED:
            return "MH_ERROR_ALREADY_CREATED";
        case MH_ERROR_NOT_CREATED:
            return "MH_ERROR_NOT_CREATED";
        case MH_ERROR_ENABLED:
            return "MH_ERROR_ENABLED";
        case MH_ERROR_DISABLED:
            return "MH_ERROR_DISABLED";
        case MH_ERROR_NOT_EXECUTABLE:
            return "MH_ERROR_NOT_EXECUTABLE";
        case MH_ERROR_UNSUPPORTED_FUNCTION:
            return "MH_ERROR_UNSUPPORTED_FUNCTION";
        case MH_ERROR_MEMORY_ALLOC:
            return "MH_ERROR_MEMORY_ALLOC";
        case MH_ERROR_MEMORY_PROTECT:
            return "MH_ERROR_MEMORY_PROTECT";
        case MH_ERROR_MODULE_NOT_FOUND:
            return "MH_ERROR_MODULE_NOT_FOUND";
        case MH_ERROR_FUNCTION_NOT_FOUND:
            return "MH_ERROR_FUNCTION_NOT_FOUND";
        default:
            return "Unknown error";
        }
    }
};

// RAII Hook包装类
template<typename FuncType>
class Hook
{
public:
    Hook(FuncType targetFunc, FuncType detourFunc)
        : target_(targetFunc)
        , detour_(detourFunc)
        , original_(nullptr)
        , enabled_(false)
    {
        auto &manager = HookManager::getInstance();
        if (manager.createHook(targetFunc, detourFunc, &original_))
        {
            enabled_ = true;
        }
    }

    Hook(const std::string &moduleName, const std::string &funcName, FuncType detourFunc)
        : target_(nullptr)
        , detour_(detourFunc)
        , original_(nullptr)
        , enabled_(false)
    {
        auto &manager = HookManager::getInstance();
        if (manager.createAPIHook(moduleName, funcName, reinterpret_cast<LPVOID>(detourFunc), reinterpret_cast<LPVOID *>(&original_)))
        {
            enabled_ = true;
        }
    }

    // 新增：通过偏移构造Hook
    Hook(const std::string &moduleName, DWORD offset, FuncType detourFunc)
        : target_(nullptr)
        , detour_(detourFunc)
        , original_(nullptr)
        , enabled_(false)
    {
        auto &manager = HookManager::getInstance();

        // 获取目标地址
        LPVOID targetAddr = manager.GetAddressByOffset(moduleName, offset);
        if (targetAddr)
        {
            target_ = reinterpret_cast<FuncType>(targetAddr);

            // 创建Hook
            if (manager.createOffsetHook(moduleName, offset, reinterpret_cast<LPVOID>(detourFunc), reinterpret_cast<LPVOID *>(&original_)))
            {
                enabled_ = true;
            }
        }
    }

    ~Hook()
    {
        if (enabled_ && target_)
        {
            MH_DisableHook(reinterpret_cast<LPVOID>(target_));
        }
    }

    // 获取原始函数指针
    FuncType getOriginal() const
    {
        return original_;
    }

    // 检查Hook是否成功
    bool isValid() const
    {
        return enabled_;
    }

    // 调用原始函数的便捷方法
    template<typename... Args>
    auto callOriginal(Args &&...args) -> decltype(original_(std::forward<Args>(args)...))
    {
        if (original_)
        {
            return original_(std::forward<Args>(args)...);
        }
        throw std::runtime_error("Original function not available");
    }

private:
    FuncType target_;
    FuncType detour_;
    FuncType original_; // 直接存储函数指针，不是指针的指针
    bool     enabled_;
};

} // namespace EasyHook

// 便捷宏定义 - 重新设计，更简洁可靠
#define DECLARE_HOOK(FuncName, RetType, ...)                                    \
    typedef RetType(WINAPI *FuncName##_t)(__VA_ARGS__);                         \
    inline std::unique_ptr<EasyHook::Hook<FuncName##_t>> &get_hook_##FuncName() \
    {                                                                           \
        static std::unique_ptr<EasyHook::Hook<FuncName##_t>> instance;          \
        return instance;                                                        \
    }                                                                           \
    inline FuncName##_t get_original_##FuncName()                               \
    {                                                                           \
        auto &hook_ptr = get_hook_##FuncName();                                 \
        return hook_ptr ? hook_ptr->getOriginal() : nullptr;                    \
    }                                                                           \
    RetType WINAPI Detour##FuncName(__VA_ARGS__)

#define IMPLEMENT_HOOK(FuncName, ModuleName, FuncNameStr)                                                           \
    inline void Install##FuncName##Hook()                                                                           \
    {                                                                                                               \
        auto &hook_ptr = get_hook_##FuncName();                                                                     \
        hook_ptr       = std::make_unique<EasyHook::Hook<FuncName##_t>>(ModuleName, FuncNameStr, Detour##FuncName); \
        if (!hook_ptr->isValid())                                                                                   \
        {                                                                                                           \
            std::cerr << "Failed to install " #FuncName " hook!" << std::endl;                                      \
        }                                                                                                           \
        else                                                                                                        \
        {                                                                                                           \
            std::cout << "Successfully installed " #FuncName " hook!" << std::endl;                                 \
        }                                                                                                           \
    }

#define IMPLEMENT_DIRECT_HOOK(FuncName, TargetAddr)                                                                                    \
    inline void Install##FuncName##Hook()                                                                                              \
    {                                                                                                                                  \
        auto &hook_ptr = get_hook_##FuncName();                                                                                        \
        hook_ptr       = std::make_unique<EasyHook::Hook<FuncName##_t>>(reinterpret_cast<FuncName##_t>(TargetAddr), Detour##FuncName); \
        if (!hook_ptr->isValid())                                                                                                      \
        {                                                                                                                              \
            std::cerr << "Failed to install " #FuncName " hook!" << std::endl;                                                         \
        }                                                                                                                              \
        else                                                                                                                           \
        {                                                                                                                              \
            std::cout << "Successfully installed " #FuncName " hook!" << std::endl;                                                    \
        }                                                                                                                              \
    }

// ================================
// 新增：偏移Hook宏
// ================================

#define IMPLEMENT_OFFSET_HOOK(FuncName, ModuleName, Offset)                                                                                       \
    inline void Install##FuncName##OffsetHook()                                                                                                   \
    {                                                                                                                                             \
        auto &hook_ptr = get_hook_##FuncName();                                                                                                   \
        hook_ptr       = std::make_unique<EasyHook::Hook<FuncName##_t>>(ModuleName, static_cast<DWORD>(Offset), Detour##FuncName);                \
        if (!hook_ptr->isValid())                                                                                                                 \
        {                                                                                                                                         \
            std::cerr << "Failed to install " #FuncName " offset hook at " << ModuleName << "+0x" << std::hex << Offset << "!" << std::endl;      \
        }                                                                                                                                         \
        else                                                                                                                                      \
        {                                                                                                                                         \
            std::cout << "Successfully installed " #FuncName " offset hook at " << ModuleName << "+0x" << std::hex << Offset << "!" << std::endl; \
        }                                                                                                                                         \
    }

// 便捷的偏移Hook宏
#define HOOK_BY_OFFSET(moduleName, offset, detourFunc)                                                                                                                        \
    do                                                                                                                                                                        \
    {                                                                                                                                                                         \
        auto &mgr = EasyHook::HookManager::getInstance();                                                                                                                     \
        mgr.initialize();                                                                                                                                                     \
        LPVOID addr = mgr.GetAddressByOffset(moduleName, static_cast<DWORD>(offset));                                                                                         \
        if (addr)                                                                                                                                                             \
        {                                                                                                                                                                     \
            if (mgr.createOffsetHook(moduleName, static_cast<DWORD>(offset), reinterpret_cast<LPVOID>(detourFunc)))                                                           \
            {                                                                                                                                                                 \
                std::cout << "Successfully hooked " << moduleName << "+0x" << std::hex << (offset) << " at 0x" << reinterpret_cast<uintptr_t>(addr) << std::dec << std::endl; \
            }                                                                                                                                                                 \
            else                                                                                                                                                              \
            {                                                                                                                                                                 \
                std::cout << "Failed to hook " << moduleName << "+0x" << std::hex << (offset) << std::dec << std::endl;                                                       \
            }                                                                                                                                                                 \
        }                                                                                                                                                                     \
        else                                                                                                                                                                  \
        {                                                                                                                                                                     \
            std::cout << "Failed to get address for " << moduleName << "+0x" << std::hex << (offset) << std::dec << std::endl;                                                \
        }                                                                                                                                                                     \
    }                                                                                                                                                                         \
    while (0)

// 显示地址信息的便捷宏
#define SHOW_FUNCTION_ADDRESS(moduleName, functionName)                                                                                             \
    do                                                                                                                                              \
    {                                                                                                                                               \
        auto  &mgr  = EasyHook::HookManager::getInstance();                                                                                         \
        LPVOID addr = mgr.GetFunctionAddress(moduleName, functionName);                                                                             \
        if (addr)                                                                                                                                   \
        {                                                                                                                                           \
            std::cout << functionName << " (" << moduleName << ") -> 0x" << std::hex << reinterpret_cast<uintptr_t>(addr) << std::dec << std::endl; \
        }                                                                                                                                           \
        else                                                                                                                                        \
        {                                                                                                                                           \
            std::cout << functionName << " not found in " << moduleName << std::endl;                                                               \
        }                                                                                                                                           \
    }                                                                                                                                               \
    while (0)

#define SHOW_MODULE_BASE(moduleName)                                                                                                     \
    do                                                                                                                                   \
    {                                                                                                                                    \
        HMODULE hModule = GetModuleHandleA(moduleName);                                                                                  \
        if (hModule)                                                                                                                     \
        {                                                                                                                                \
            std::cout << moduleName << " base address: 0x" << std::hex << reinterpret_cast<uintptr_t>(hModule) << std::dec << std::endl; \
        }                                                                                                                                \
        else                                                                                                                             \
        {                                                                                                                                \
            std::cout << moduleName << " not loaded" << std::endl;                                                                       \
        }                                                                                                                                \
    }                                                                                                                                    \
    while (0)

// 获取原始函数的便捷宏
#define Original(FuncName) get_original_##FuncName()

// 简化的Hook安装宏
#define INSTALL_HOOK(FuncName)        Install##FuncName##Hook()
#define INSTALL_OFFSET_HOOK(FuncName) Install##FuncName##OffsetHook()

// Hook管理宏
#define BEGIN_HOOK_SETUP()                                                            \
    struct HookSetup                                                                  \
    {                                                                                 \
        HookSetup()                                                                   \
        {                                                                             \
            auto &mgr = EasyHook::HookManager::getInstance();                         \
            if (!mgr.initialize())                                                    \
            {                                                                         \
                std::cerr << "Hook init failed: " << mgr.getLastError() << std::endl; \
                return;                                                               \
            }                                                                         \
            std::cout << "Hook system initialized!" << std::endl;

#define ADD_HOOK(name) INSTALL_HOOK(name);

#define END_HOOK_SETUP()                                           \
    std::cout << "All hooks installed successfully!" << std::endl; \
    }                                                              \
    ~HookSetup()                                                   \
    {                                                              \
        EasyHook::HookManager::getInstance().cleanup();            \
        std::cout << "Hooks cleaned up!" << std::endl;             \
    }                                                              \
    }                                                              \
    g_hookSetup;

// 简化版本 - 直接在全局作用域安装Hook
#define SETUP_HOOKS()                                                                           \
    struct GlobalHookInitializer                                                                \
    {                                                                                           \
        GlobalHookInitializer()                                                                 \
        {                                                                                       \
            auto &mgr = EasyHook::HookManager::getInstance();                                   \
            if (!mgr.initialize())                                                              \
            {                                                                                   \
                std::cerr << "Hook initialization failed: " << mgr.getLastError() << std::endl; \
                return;                                                                         \
            }

#define INSTALL_HOOK_HERE(name)        INSTALL_HOOK(name);
#define INSTALL_OFFSET_HOOK_HERE(name) INSTALL_OFFSET_HOOK(name);

#define FINISH_HOOK_SETUP()                             \
    }                                                   \
    ~GlobalHookInitializer()                            \
    {                                                   \
        EasyHook::HookManager::getInstance().cleanup(); \
    }                                                   \
    }                                                   \
    g_globalHooks;

#endif // __EASY_HOOK_H__